package service

import (
	"chat/log"
	"chat/models"
	"chat/utils"
	"fmt"
	"math/rand"
	"strconv"
	"time"

	"github.com/dgrijalva/jwt-go"
	"github.com/gin-gonic/gin"
	"go.uber.org/zap"
)

// Login
// @Summary 用户登录
// @Tags 用户模块
// @Param name formData string flase "name"
// @Param password formData string flase "password"
// @Param phone formData string flase "phone"
// @Param email formData string flase "email"
// @Success 200 {string} json{"code","message"}
// @Router /user/login [post]
func Login(c *gin.Context) {
	var user models.UserBasic
	if err := c.ShouldBindJSON(&user); err != nil {
		log.Error("参数错误")
		utils.RespFail(c.Writer, "参数错误")
		return
	}
	fmt.Printf("%v\n", user)

	password := user.PassWord
	if user.LastLoginAction == "phone" {
		user, _ = models.FindUserByPhone(user.Name)
	} else if user.LastLoginAction == "email" {
		user, _ = models.FindUserByEmail(user.Name)
	} else {
		user, _ = models.FindUserByName(user.Name)
	}
	flag := utils.ValidPassword(password, user.Salt, user.PassWord)
	if user.Name == "" || !flag {
		utils.RespFail(c.Writer, "用户名或密码错误")
		return
	}
	// if user.IsLogin {
	// 	utils.RespFail(c.Writer, "请勿重复登录")
	// 	return
	// }
	claims := utils.Claims{
		UserID: strconv.FormatUint(uint64(user.ID), 10),
		StandardClaims: jwt.StandardClaims{
			ExpiresAt: time.Now().Add(time.Hour * 10).Unix(), // 过期时间为2小时
		},
	}
	token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
	tokenString, err := token.SignedString(utils.JwtSecret)
	if err != nil {
		utils.RespTokenFail(c.Writer, "Failed to generate JWT")
		return
	}
	user.LoginTime = time.Now()
	user.IsLogin = true
	user.Identity = tokenString
	models.UpdateUser(&user)

	utils.RespOk(c.Writer, user, "")
}

func Logout(c *gin.Context) {
	var user models.UserBasic
	if err := c.ShouldBindJSON(&user); err != nil {
		log.Error("参数错误")
		utils.RespFail(c.Writer, "参数错误")
		return
	}
	user.IsLogin = false
	user.LoginTime = time.Now()
	user.Identity = ""
	if err := models.UpdateUser(&user); err != nil {
		utils.RespFail(c.Writer, "退出登录失败")
		return
	}
	utils.RespOk(c.Writer, user, "")
}

// Register
// @Summary 用户注册
// @Tags 用户模块
// @Param name formData string flase "name"
// @Param password formData string flase "password"
// @Param phone formData string flase "phone"
// @Param email formData string flase "email"
// @Success 200 {string} json{"code","message"}
// @Router /user/register [post]
func Register(c *gin.Context) {
	user := struct {
		models.UserBasic
		Code string
	}{}
	if err := c.ShouldBindJSON(&user); err != nil {
		log.Error("参数错误")
		utils.RespFail(c.Writer, "参数错误")
		return
	}
	var verificationCode string
	if user.Phone != "" {
		phone, _ := models.FindUserByPhone(user.Phone)
		if phone.Phone != "" {
			log.Error("该手机号已注册")
			utils.RespFail(c.Writer, "该手机号已注册")
			return
		}
		verificationCode, _ = utils.GetVerificationCodeFromRedis(user.Phone)
	} else if user.Email != "" {
		email, _ := models.FindUserByEmail(user.Email)
		if email.Email != "" {
			log.Error("该邮箱已注册")
			utils.RespFail(c.Writer, "该邮箱已注册")
			return
		}
		verificationCode, _ = utils.GetVerificationCodeFromRedis(user.Email)
	}
	if user.Code != verificationCode {
		utils.RespFail(c.Writer, "验证码错误")
		return
	}
	name, _ := models.FindUserByName(user.Name)
	if name.Name != "" {
		str := `用户名` + name.Name + `已注册，`
		log.Error(str)
		utils.RespFail(c.Writer, str+"是否已忘记密码？")
		return
	}
	user.Salt = fmt.Sprintf("%06d", rand.Int31())
	user.PassWord = utils.MakePassword(user.PassWord, user.Salt)
	user.LoginTime = time.Now()
	user.HeartbeatTime = time.Now()
	user.LogoutTime = time.Now()
	user.Type = 1
	user.Code = ""
	user.Avatar = "http://" + c.Request.Host + "/static/upload/avatar/default.jpeg"
	if err := models.CreateUser(&user.UserBasic); err != nil {
		log.Error("数据库操作失败:", zap.Error(err))
		utils.RespFail(c.Writer, "用户注册失败")
		return
	}
	utils.RespOk(c.Writer, nil, "用户注册成功,三秒后跳转")
}

// GetVerificationCode
// @Summary 获取验证码
// @Tags 用户模块
// @Param type Query string flase "type"
// @Param phone Query string flase "phone"
// @Param email Query string flase "email"
// @Success 200 {string} json{"code","message"}
// @Router /user/get-verification-code [get]
func GetVerificationCode(c *gin.Context) {
	action := c.Query("type")
	code := utils.GenerateVerificationCode()
	if action == "email" {
		email := c.Query("email")
		utils.SaveVerificationCode(email, code)
		if err := utils.SendToMail(email, code); err != nil {
			utils.RespFail(c.Writer, "发送邮箱失败,错误信息"+err.Error())
			return
		}
	} else if action == "phone" {
		phone := c.Query("phone")
		utils.SaveVerificationCode(phone, code)
	} else {
		utils.RespFail(c.Writer, "参数错误")
		return
	}
	utils.RespOk(c.Writer, code, "验证码获取成功")
}

// GetNewFriendOrGroups
// @Summary 搜索新朋友或群组
// @Tags 用户模块
// @Param name Query string flase "name"
// @Success 200 {string} json{"code","message"}
// @Router /user/new-friends-or-groups [get]
func GetNewFriendOrGroups(c *gin.Context) {
	name := c.Query("name")

	friends, _ := models.FindNewFriends(name)
	groups, _ := models.FindNewGroup(name)
	data := map[string]interface{}{
		"查找好友": &friends,
		"查找群":  &groups,
	}
	utils.RespOkList(c.Writer, data, "")
}

// GetHistoryList
// @Summary 获取聊天记录
// @Tags 用户模块
// @Param type Query int flase "type"
// @Param target_id Query string flase "target_id"
// @Param form_id Query string flase "form_id"
// @Success 200 {string} json{"code","message"}
// @Router /user/get-verification-code [get]
func GetHistoryList(c *gin.Context) {
	action := c.Query("type")
	FormId := c.Query("form_id")
	TargerId := c.Query("target_id")
	if action == "0" {
		history, err := models.FindFriendChatHistory(FormId, TargerId)
		if err != nil {
			utils.RespFail(c.Writer, "获取聊天记录失败")
			return
		}
		utils.RespOkList(c.Writer, history, len(history))
		return
	} else if action == "1" {
		history, err := models.FindGroupChatHistory(TargerId)
		if err != nil {
			utils.RespFail(c.Writer, "获取聊天记录失败")
			return
		}
		utils.RespOkList(c.Writer, history, len(history))
		return
	}
}

func ApplyFriend(c *gin.Context) {
	var contact models.Contact
	if err := c.ShouldBindJSON(&contact); err != nil {
		log.Error("参数错误")
		utils.RespFail(c.Writer, "参数错误")
		return
	}
	res, str, err := models.ApplyFriend(contact)
	if err != nil {
		utils.RespFail(c.Writer, "Apply friend failed ， please try again")
		return
	}
	utils.RespOk(c.Writer, res, str)
}

func NewFirendApply(c *gin.Context) {
	ID := c.Query("id")
	friends, groups := models.GetApplyList(ID)
	type FriendGroups struct {
		Friends []*models.Contact
		Groups  []*models.Contact
	}
	friendGroups := FriendGroups{
		Friends: friends,
		Groups:  groups,
	}
	utils.RespOk(c.Writer, friendGroups, "")
}

func AgreeNewApply(c *gin.Context) {
	contact := models.Contact{}
	if err := c.ShouldBindJSON(&contact); err != nil {
		log.Error("参数错误")
		utils.RespFail(c.Writer, "参数错误")
		return
	}
	contact.AgreeOrNot = true
	contact, err := models.AgreeFriendApply(contact)
	if err != nil {
		utils.RespFail(c.Writer, "网络请求失败，请再试一次")
		return
	}
	utils.RespOk(c.Writer, "", "已添加好友")
}

func GetFriendList(c *gin.Context) {
	id := c.Query("id")
	friends, err := models.GetUserList(id)
	if err != nil {
		utils.RespFail(c.Writer, "获取好友列表失败，请检查网络或联系管理员")
		return
	}
	utils.RespOkList(c.Writer, friends, "")
}

func HasOnLine(c *gin.Context) {
	idStr := c.Query("id")
	id, err := strconv.Atoi(idStr)
	if err != nil {
		utils.RespFail(c.Writer, "Invalid user ID. Please provide a valid numeric ID.")
		return
	}
	// Convert id from int to uint
	uintID := uint(id)
	// Check if user is online
	isOnline, err := utils.IsUserOnline(uintID)
	if err != nil {
		utils.RespFail(c.Writer, "Failed to check if user is online. Please try again or contact an administrator.")
		return
	}
	if isOnline {
		utils.RespOk(c.Writer, nil, "")
	} else {
		utils.RespFail(c.Writer, "该用户不在线")
	}
}

func EditProfile(c *gin.Context) {
	var user models.UserBasic
	if err := c.ShouldBindJSON(&user); err != nil {
		log.Error("参数错误")
		utils.RespFail(c.Writer, "参数错误")
		return
	}
	if err := models.UpdateUser(&user); err != nil {
		log.Error("操作失败")
		utils.RespFail(c.Writer, "操作失败，请联系管理员")
		return
	}
	res, _ := models.FindUserByID(strconv.Itoa(int(user.ID)))
	utils.RespOk(c.Writer, res, "修改个人信息成功")
}
